package com.supreme.studyserver.controller;

import com.alibaba.fastjson.JSONObject;
import com.supreme.common.constant.ConsoleColors;
import com.supreme.common.dto.OmsDept;
import com.supreme.common.dto.ResBase;
import com.supreme.common.dto.ResObject;
import com.supreme.common.dto.ResString;
import com.supreme.commonboot.utils.AjaxResp;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequestMapping(value = "http")
public class HttpController {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @GetMapping(value = "setToRedis/{key}/{val}")
    public AjaxResp setToRedis(@PathVariable(value = "key") String key, @PathVariable(value = "val") String val) {
        redisTemplate.opsForValue().set(key, val);
        redisTemplate.opsForValue().set(key, val, 1, TimeUnit.MINUTES);
        return AjaxResp.instance();
    }

    @GetMapping(value = "omsStoreList")
    public AjaxResp omsStoreList(@RequestParam(value = "syncType", defaultValue = "1") Integer syncType,
                                 @RequestParam(value = "storeCode", required = false) String storeCode) {
        ConsoleColors.printf(ConsoleColors.WHITE_BOLD_BRIGHT, "threadName = %s\n", Thread.currentThread().getName());

        CompletableFuture<List<OmsDept>> listCompletableFuture = CompletableFuture.supplyAsync(() -> {
            ConsoleColors.printf(ConsoleColors.PURPLE_BOLD_BRIGHT, "threadName = %s\n", Thread.currentThread().getName());

            if (syncType > 1) {
                throw new RuntimeException("syncType cannot be more than 1");
            }

            URI requestUri = UriComponentsBuilder.fromHttpUrl("http://localhost:9633/omni/test/biz/deptList")
                    .queryParam("syncType", syncType)
                    .queryParam("storeCode", storeCode)
                    .build().encode().toUri();
            String stringResult = restTemplate.getForObject(requestUri, String.class);
            return stringResult;
        }).thenApply(new Function<String, List<OmsDept>>() {
            @Override
            public List<OmsDept> apply(String s) {
                return Optional.ofNullable(JSONObject.parseObject(s, ResString.class))
                        .map(ResBase::getData)
                        .flatMap(dataString -> Optional.ofNullable(JSONObject.parseObject(dataString, OmsDept[].class)))
                        .map(omsDeptArray -> Stream.of(omsDeptArray).collect(Collectors.toList()))
                        .orElse(new ArrayList<>());
            }
        }).whenComplete(new BiConsumer<List<OmsDept>, Throwable>() {
            @Override
            public void accept(List<OmsDept> omsDeptList, Throwable throwable) {
                Optional.ofNullable(omsDeptList).ifPresent(omsDeptList1 -> ConsoleColors.printf(ConsoleColors.RED_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), omsDeptList1.size()));
                Optional.ofNullable(throwable).ifPresent(throwable1 -> System.out.println("throwable.getMessage() = " + throwable1.getMessage()));
            }
        });

        /*.thenRun(new Runnable() {
            @Override
            public void run() {
                ConsoleColors.printf(ConsoleColors.RED_BOLD_BRIGHT, "threadName = %s\n", Thread.currentThread().getName());
            }
        })*/

        /*.thenAccept(new Consumer<List<OmsDept>>() {
            @Override
            public void accept(List<OmsDept> omsDeptList) {
                ConsoleColors.printf(ConsoleColors.RED_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), omsDeptList.size());
            }
        })*/

        /*.thenApply(new Function<List<OmsDept>, Integer>() {
            @Override
            public Integer apply(List<OmsDept> omsDeptList) {
                ConsoleColors.printf(ConsoleColors.RED_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), omsDeptList.size());
                return omsDeptList.size();
            }
        })*/

        /*.whenComplete(new BiConsumer<List<OmsDept>, Throwable>() {
            @Override
            public void accept(List<OmsDept> omsDeptList, Throwable throwable) {
                Optional.ofNullable(omsDeptList).ifPresent(omsDeptList1 -> ConsoleColors.printf(ConsoleColors.RED_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), omsDeptList1.size()));
                Optional.ofNullable(throwable).ifPresent(throwable1 -> System.out.println("throwable.getMessage() = " + throwable1.getMessage()));
            }
        })*/

        /*.handle(new BiFunction<List<OmsDept>, Throwable, List<OmsDept>>() {
            @Override
            public List<OmsDept> apply(List<OmsDept> omsDeptList, Throwable throwable) {
                Optional.ofNullable(omsDeptList).ifPresent(omsDeptList1 -> ConsoleColors.printf(ConsoleColors.RED_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), omsDeptList1.size()));
                Optional.ofNullable(throwable).ifPresent(throwable1 -> System.out.println("throwable.getMessage() = " + throwable1.getMessage()));
                return Optional.ofNullable(omsDeptList).map(List::size).orElse(0);
            }
        })*/

        try {
            List<OmsDept> omsDeptList = listCompletableFuture.get();
            ConsoleColors.printf(ConsoleColors.BLUE_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), omsDeptList.size());
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        /*try {
            Integer integer = integerCompletableFuture.get();
            ConsoleColors.printf(ConsoleColors.BLUE_BOLD_BRIGHT, "threadName = %s %d\n", Thread.currentThread().getName(), integer);
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }*/

        /*try {
            voidCompletableFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }*/

        ConsoleColors.printf(ConsoleColors.WHITE_BOLD_BRIGHT, "FINISH threadName = %s\n", Thread.currentThread().getName());
        return AjaxResp.instance();
    }

    @GetMapping(value = "getStoreListToRedis")
    public AjaxResp getStoreListToRedis(@RequestParam(value = "syncType", defaultValue = "1") Integer syncType,
                                        @RequestParam(value = "storeCode", required = false) String storeCode) {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            URI requestUri = UriComponentsBuilder.fromHttpUrl("http://localhost:9633/omni/test/biz/deptList")
                    .queryParam("syncType", syncType)
                    .queryParam("storeCode", storeCode)
                    .build().encode().toUri();
            String stringResult = restTemplate.getForObject(requestUri, String.class);
            return stringResult;
        }).thenApply(s -> {
            ResString resString = JSONObject.parseObject(s, ResString.class);
            OmsDept[] omsDeptArray = JSONObject.parseObject(resString.getData(), OmsDept[].class);
            return omsDeptArray;
        }).handle((omsDeptArray, throwable) -> {
            Optional.ofNullable(throwable).map(Throwable::getMessage).ifPresent(System.out::println);
            redisTemplate.delete("STORE_LIST");
            redisTemplate.opsForList().rightPushAll("STORE_LIST", omsDeptArray);
            return omsDeptArray.length;
        });

        try {
            Integer result = completableFuture.get();
            System.out.println("result = " + result);
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        List<Object> omsDeptArray =  redisTemplate.opsForList().range("STORE_LIST", 0, -1);

        return AjaxResp.instance(omsDeptArray);
    }
}
